#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define N 2048  
#define ITER 1 

int A[N][N];
int B[N][N];
int C[N][N];
int tmp[N][N];

void M0(int L[][N], int R[][N], int M[][N]) {
    int i, j, k;

    for (i = 0; i < N; ++i)
        for (j = 0; j < N; ++j)
            M[i][j] = 0;

    for (i = 0; i < N; ++i) {
        for (j = 0; j < N; ++j) {
            for (k = 0; k < N; ++k) {
                M[i][j] += L[i][k] * R[k][j];
            }
        }
    }
}

void M1(int L[][N], int R[][N], int M[][N]) {
    int i, j, k;

    for (i = 0; i < N; ++i)
        for (j = 0; j < N; ++j)
            M[i][j] = 0;

    for (i = 0; i < N; ++i)
        for (j = 0; j < N; ++j)
            tmp[i][j] = R[j][i];

    for (i = 0; i < N; ++i) {
        for (j = 0; j < N; ++j) {
            for (k = 0; k < N; ++k) {
                M[i][j] += L[i][k] * tmp[j][k];
            }
        }
    }
}

void M2(int L[][N], int R[][N], int M[][N]) {
    int i, j, k;

    for (i = 0; i < N; ++i)
        for (j = 0; j < N; ++j)
            M[i][j] = 0;

    for (k = 0; k < N; ++k) {
        for (i = 0; i < N; ++i) {
            for (j = 0; j < N; ++j) {
                M[i][j] += L[i][k] * R[k][j];
            }
        }
    }
}

void M3(int L[][N], int R[][N], int M[][N]) {
    int i, j, k, jj, kk;
    int B = 64;

    for (i = 0; i < N; ++i)
        for (j = 0; j < N; ++j)
            M[i][j] = 0;

    for (jj = 0; jj < N; jj += B) {
        for (kk = 0; kk < N; kk += B) {
            for (i = 0; i < N; ++i) {
                for (j = jj; j < jj + B; ++j) {
                    for (k = kk; k < kk + B; ++k) {
                        M[i][j] += L[i][k] * R[k][j];
                    }
                }
            }
        }
    }
}

void M4(int L[][N], int R[][N], int M[][N]) {
    int i, j, k, jj, kk;
    int B = 64;

    for (i = 0; i < N; ++i)
        for (j = 0; j < N; ++j)
            M[i][j] = 0;

    for (i = 0; i < N; ++i)
        for (j = 0; j < N; ++j)
            tmp[i][j] = R[j][i];

    for (jj = 0; jj < N; jj += B) {
        for (kk = 0; kk < N; kk += B) {
            for (i = 0; i < N; ++i) {
                for (j = jj; j < jj + B; ++j) {
                    for (k = kk; k < kk + B; ++k) {
                        M[i][j] += L[i][k] * tmp[j][k];
                    }
                }
            }
        }
    }
}

void M5(int L[][N], int R[][N], int M[][N]) {
    int i, j, k, jj, kk;
    int B = 64;

    for (i = 0; i < N; ++i)
        for (j = 0; j < N; ++j)
            M[i][j] = 0;

    for (jj = 0; jj < N; jj += B) {
        for (kk = 0; kk < N; kk += B) {
            for (k = kk; k < kk + B; ++k) {
                for (i = 0; i < N; ++i) {
                    for (j = jj; j < jj + B; ++j) {
                        M[i][j] += L[i][k] * R[k][j];
                    }
                }
            }
        }
    }
}

int main() {
    int iter;
    clock_t start, end;
    double duration;
    void (*func)(int[][N], int[][N], int[][N]);
    func = M5;

    start = clock();
    for (iter = 0; iter < ITER; ++iter) {
        func(A, B, C);
        func(C, A, B);
        func(B, C, A);
    }
    end = clock();

    duration = (double)(end - start);
    printf("N: %d, ITER: %d, time: %.4f\n", N, ITER, (duration / CLOCKS_PER_SEC));

    return 0;
}


